home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / IFF_SCRATCH / iffread.m next >
Encoding:
Text File  |  1992-05-21  |  9.7 KB  |  343 lines

  1. /* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. **
  12. ** Modified by Mark Thompson on 10/4/90 to accomodate 24 bit IFF files
  13. ** as used by ASDG, NewTek, etc.
  14. */
  15.  
  16. #import <stdio.h>
  17. #import <stdlib.h>
  18. #import <streams/streams.h>
  19. #import <strings.h>
  20. #import "kludge.h"
  21. #import "ilbm.h"
  22.  
  23. static void getfourchars(NXStream* f, char fourchars[4]);
  24. static unsigned char get_byte( NXStream* f );
  25.  
  26. void main(int argc, char *argv[])
  27. {
  28.     NXStream* ifp;
  29.     pixel* pixelrow;
  30.     pixel* colormap = 0;
  31.     int argn, colors, i, j, r, g, b, byte, bytes;
  32.     short rows, cols = 0, row, col;
  33.         int maxval;
  34.     char iffid[5];
  35.     unsigned char* body = 0;
  36.     unsigned char* bp;
  37.     unsigned char* ubp;
  38.     unsigned char* rawrow;
  39.     unsigned char* runbuf;
  40.     unsigned char* Rrow;
  41.     unsigned char* Grow;
  42.     unsigned char* Brow;
  43.     long formsize, bytesread, chunksize, viewportmodes = 0;
  44.     int nPlanes, masking, compression, xAsp, yAsp, ham, hammask, allPlanes;
  45.  
  46. /*
  47.     ppm_init( &argc, argv );
  48.  
  49.     argn = 1;
  50.  
  51.     if ( argn < argc ) {
  52.         ifp = pm_openr( argv[argn] );
  53.         argn++;
  54.     } else
  55.         ifp = stdin;
  56.  
  57.     if ( argn != argc )
  58.         pm_usage( "[ilbmfile]" );
  59. */
  60.     ifp = pm_openr( argv[argn] );
  61.  
  62.     /* Read in the ILBM file. */
  63.     iffid[4] = '\0';
  64.     getfourchars( ifp, iffid );
  65.     if ( strcmp( iffid, "FORM" ) != 0 )
  66.         pm_error( "input is not a FORM type IFF file" );
  67.     if ( pm_readbiglong( ifp, &formsize ) == -1 )
  68.         pm_error( "EOF / read error" );
  69.     getfourchars( ifp, iffid );
  70.     if ( strcmp( iffid, "ILBM" ) != 0 )
  71.         pm_error( "input is not an ILBM type FORM IFF file" );
  72.     bytesread = 12;
  73.  
  74.     /* Main loop, parsing the IFF FORM. */
  75.     while ( bytesread < formsize ) {
  76.         getfourchars( ifp, iffid );
  77.         if ( pm_readbiglong( ifp, &chunksize ) == -1 )
  78.             pm_error( "EOF / read error" );
  79.         bytesread += 8;
  80.  
  81.         if ( body != 0 ) {
  82.             fprintf(stderr, "\"%s\" chunk found after BODY chunk - skipping", iffid );
  83.             for ( i = 0; i < chunksize; i++ )
  84.                 (void) get_byte( ifp );
  85.         } else if ( strcmp( iffid, "BMHD" ) == 0 ) {
  86.             short junk;
  87.             if ( pm_readbigshort( ifp, &cols ) == -1 )
  88.                 pm_error( "EOF / read error" );
  89.             if ( pm_readbigshort( ifp, &rows ) == -1 )
  90.                 pm_error( "EOF / read error" );
  91.             if ( pm_readbigshort( ifp, &junk ) == -1 )
  92.                 pm_error( "EOF / read error" );
  93.             if ( pm_readbigshort( ifp, &junk ) == -1 )
  94.                 pm_error( "EOF / read error" );
  95.             nPlanes = get_byte( ifp );
  96.             masking = get_byte( ifp );
  97.             compression = get_byte( ifp );
  98.             (void) get_byte( ifp );    /* pad1 */
  99.             if ( pm_readbigshort( ifp, &junk ) == -1 ) /* transparentColor */
  100.             pm_error( "EOF / read error" );
  101.             xAsp = get_byte( ifp );
  102.             yAsp = get_byte( ifp );
  103.             if ( pm_readbigshort( ifp, &junk ) == -1 ) /* pageWidth */
  104.                 pm_error( "EOF / read error" );
  105.             if ( pm_readbigshort( ifp, &junk ) == -1) /* pageHeight */
  106.                 pm_error( "EOF / read error" );
  107.         } else if ( strcmp( iffid, "CMAP" ) == 0 ) {
  108.             colors = chunksize / 3;
  109.             if ( colors > 0 ) {
  110.                 colormap = ppm_allocrow( colors );
  111.                 for ( i = 0; i < colors; i++ ) {
  112.                     r = get_byte( ifp );
  113.                     g = get_byte( ifp );
  114.                     b = get_byte( ifp );
  115.                     PPM_ASSIGN( colormap[i], r, g, b );
  116.                 }
  117.                 if ( colors * 3 != chunksize )
  118.                     (void) get_byte( ifp );
  119.             }
  120.         } else if ( strcmp( iffid, "CAMG" ) == 0 ) {
  121.             if ( pm_readbiglong( ifp, &viewportmodes ) == -1 )
  122.                 pm_error( "EOF / read error" );
  123.         } else if ( strcmp( iffid, "BODY" ) == 0 ) {
  124.             body = (unsigned char*) malloc( chunksize );
  125.             if ( body == 0 )
  126.                 pm_error( "out of memory" );
  127.             if ( fread( body, 1, chunksize, ifp ) != chunksize )
  128.                 pm_error( "EOF / read error reading BODY chunk" );
  129.         } else if ( strcmp( iffid, "GRAB" ) == 0 ||
  130.                 strcmp( iffid, "DEST" ) == 0 ||
  131.                 strcmp( iffid, "SPRT" ) == 0 ||
  132.                 strcmp( iffid, "CRNG" ) == 0 ||
  133.                 strcmp( iffid, "CCRT" ) == 0 ||
  134.                 strcmp( iffid, "DPPV" ) == 0 ) {
  135.             for ( i = 0; i < chunksize; i++ )
  136.                 (void) get_byte( ifp );
  137.         } else {
  138.             fprintf(stderr,  "unknown chunk type \"%s\" - skipping", iffid );
  139.             for ( i = 0; i < chunksize; i++ )
  140.                 (void) get_byte( ifp );
  141.         }
  142.  
  143.         bytesread += chunksize;
  144.     }
  145.  
  146.     pm_close( ifp );
  147.  
  148.     /* Done reading.  Now interpret what we got. */
  149.     if ( cols == 0 )
  150.         pm_error( "no BMHD chunk found" );
  151.     if ( body == 0 )
  152.         pm_error( "no BODY chunk found" );
  153.     if ( xAsp != yAsp )
  154.         fprintf(stderr, "warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
  155.             xAsp > yAsp ? 'x' : 'y',
  156.             xAsp > yAsp ? (float) xAsp / yAsp : (float) yAsp / xAsp );
  157.     if ( ( viewportmodes & vmHAM ) && nPlanes != 24 ) {
  158.         ham = 1;
  159.         hammask = ( 1 << ( nPlanes - 2 ) ) - 1;
  160.         maxval = pm_bitstomaxval( nPlanes - 2 );
  161.         if ( maxval > PPM_MAXMAXVAL )
  162.         pm_error("nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  163.         if ( colormap != 0 )
  164.             for ( i = 0; i < colors; i++ ) {
  165.                 r = PPM_GETR( colormap[i] ) >> ( 10 - nPlanes );
  166.                 g = PPM_GETG( colormap[i] ) >> ( 10 - nPlanes );
  167.                 b = PPM_GETB( colormap[i] ) >> ( 10 - nPlanes );
  168.                 PPM_ASSIGN( colormap[i], r, g, b );
  169.             }
  170.         } else {
  171.         ham = 0;
  172.         if ( colormap != 0 )
  173.             maxval = 255;        /* colormap contains bytes */
  174.         else if ( nPlanes == 24 )
  175.             maxval = 255;
  176.         else
  177.             maxval = pm_bitstomaxval( nPlanes );
  178.         if ( maxval > PPM_MAXMAXVAL )
  179.         pm_error("nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  180.     }
  181.     if ( viewportmodes & vmEXTRA_HALFBRITE ) {
  182.         pixel* tempcolormap;
  183.     
  184.         tempcolormap = ppm_allocrow( colors * 2 );
  185.         for ( i = 0; i < colors; i++ ) {
  186.             tempcolormap[i] = colormap[i];
  187.             PPM_ASSIGN(tempcolormap[colors + i], PPM_GETR(colormap[i]) / 2,
  188.                         PPM_GETG(colormap[i]) / 2, PPM_GETB(colormap[i]) / 2 );
  189.         }
  190.         ppm_freerow( colormap );
  191.         colormap = tempcolormap;
  192.         colors *= 2;
  193.     }
  194.     if ( colormap == 0 && nPlanes != 24 )
  195.         fprintf(stderr,  "no colormap - interpreting values as grayscale" );
  196.     allPlanes = nPlanes + ( masking == mskHasMask ? 1 : 0 );
  197.  
  198.     ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
  199.     pixelrow = ppm_allocrow( cols );
  200.     if ( nPlanes == 24 ) {
  201.         Rrow = (unsigned char*) malloc( cols );
  202.         Grow = (unsigned char*) malloc( cols );
  203.         Brow = (unsigned char*) malloc( cols );
  204.         if ( Rrow == 0 || Grow == 0 || Brow == 0 )
  205.             pm_error( "out of memory" );
  206.     } else {
  207.         rawrow = (unsigned char*) malloc( cols );
  208.         if ( rawrow == 0 )
  209.             pm_error( "out of memory" );
  210.     }
  211.     runbuf = (unsigned char*) malloc( RowBytes( cols ) );
  212.     if ( runbuf == 0 )
  213.         pm_error( "out of memory" );
  214.  
  215.     bp = body;
  216.     for ( row = 0; row < rows; row++ ) {
  217.     /* Extract rawrow from the image. */
  218.     if ( nPlanes == 24 )
  219.         for ( col = 0; col < cols; ++col )
  220.             Rrow[col] = Grow[col] = Brow[col] = 0;
  221.     else
  222.         for ( col = 0; col < cols; ++col )
  223.             rawrow[col] = 0;
  224.     for ( i = 0; i < allPlanes; i++ ) {
  225.         switch ( compression ) {
  226.             case cmpNone:
  227.                 ubp = bp;
  228.                 bp += RowBytes( cols );
  229.                 break;
  230.  
  231.             case cmpByteRun1:
  232.                 ubp = runbuf;
  233.                 bytes = RowBytes( cols );
  234.                 do {
  235.                     byte = *bp++;
  236.                     if ( byte <= 127 )
  237.                     for ( j = byte, bytes -= j + 1; j >= 0; j-- )
  238.                         *ubp++ = *bp++;
  239.                     else if ( byte != 128 )
  240.                         for ( j = 256 - byte, bytes -= j + 1, byte = *bp++; j >= 0; j-- )
  241.                             *ubp++ = byte;
  242.                 }
  243.                 while ( bytes > 0 );
  244.                 if ( bytes < 0 )
  245.                     pm_error( "error doing ByteRun decompression" );
  246.                     ubp = runbuf;
  247.                     break;
  248.  
  249.             default:
  250.                 pm_error( "unknown compression type" );
  251.         }
  252.  
  253.         if ( i >= nPlanes )
  254.             continue;    /* ignore mask plane */
  255.  
  256.         if ( nPlanes == 24 ) {
  257.             for ( col = 0; col < cols; col++ )
  258.                 if ( i < 8 )  { /* red */
  259.                     if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  260.                         Rrow[col] |= 1 << i;
  261.                 } else if ( i > 15 ) { /* blue */
  262.                     if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  263.                     Brow[col] |= 1 << (i-16);
  264.                 } else { /* green */
  265.                     if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  266.                         Grow[col] |= 1 << (i-8);
  267.                 }
  268.         } else
  269.             for ( col = 0; col < cols; col++ )
  270.                 if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  271.                     rawrow[col] |= 1 << i;
  272.     }
  273.  
  274.     /* Interpret rawrow into pixels. */
  275.     r = g = b = 0;
  276.     for ( col = 0; col < cols; col++ )
  277.         if ( ham ) { /* HAM mode. */
  278.             switch ( ( rawrow[col] >> nPlanes - 2 ) & 0x3 ) {
  279.                 case 0:
  280.                     if ( colormap != 0 && colors >= maxval )
  281.                         pixelrow[col] = colormap[rawrow[col] & hammask];
  282.                     else
  283.                         PPM_ASSIGN(pixelrow[col], rawrow[col] & hammask,
  284.                                 rawrow[col] & hammask, rawrow[col] & hammask );
  285.                     r = PPM_GETR( pixelrow[col] );
  286.                     g = PPM_GETG( pixelrow[col] );
  287.                     b = PPM_GETB( pixelrow[col] );
  288.                     break;
  289.  
  290.                 case 1:
  291.                     b = rawrow[col] & hammask;
  292.                     PPM_ASSIGN( pixelrow[col], r, g, b );
  293.                     break;
  294.  
  295.                 case 2:
  296.                     r = rawrow[col] & hammask;
  297.                     PPM_ASSIGN( pixelrow[col], r, g, b );
  298.                     break;
  299.  
  300.                 case 3:
  301.                     g = rawrow[col] & hammask;
  302.                     PPM_ASSIGN( pixelrow[col], r, g, b );
  303.                     break;
  304.  
  305.                 default:
  306.                     pm_error( "impossible HAM code" );
  307.             }
  308.         } else if ( nPlanes == 24 )
  309.             /* 24bit image. */
  310.             PPM_ASSIGN( pixelrow[col], Rrow[col], Grow[col], Brow[col] );
  311.         else if ( colormap != 0 )
  312.             /* Non-HAM colormapped. */
  313.             pixelrow[col] = colormap[rawrow[col]];
  314.         else
  315.             /* Non-HAM direct - weird. */
  316.             PPM_ASSIGN(pixelrow[col], rawrow[col], rawrow[col], rawrow[col] );
  317.  
  318.         /* And write out the row. */
  319.         ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
  320.     }
  321.  
  322.     exit( 0 );
  323. }
  324.  
  325. static unsigned char get_byte(NXStream *f)
  326. {
  327.     int    i;
  328.  
  329.     i = NXGetc( f );
  330.     if ( i == EOF )
  331.         pm_error( "EOF / read error" );
  332.  
  333.     return (unsigned char) i;
  334. }
  335.  
  336. static void getfourchars(NXStream *f, char fourchars[4])
  337. {
  338.     fourchars[0] = get_byte( f );
  339.     fourchars[1] = get_byte( f );
  340.     fourchars[2] = get_byte( f );
  341.     fourchars[3] = get_byte( f );
  342. }
  343.